#include "IList.h"
#include "IMemPool.h"
#include "IQueue.h"
#include "IStack.h"
#include "IStateMachine.h"
#include "hiredis.h"
#include <stdlib.h>
#include <stdio.h>

class CMyNode:public CListNode
{
public:
    CMyNode(int a){m_key = a;}
    ~CMyNode(){}
    // -1 : this < pNode
    //  0  : this = pNode
    // 1  : this > pNodep
    virtual int compare(CListNode* pNode)
    {
        if(this->m_key > ((CMyNode*)pNode)->m_key)
            return 1;
        if(this->m_key < ((CMyNode*)pNode)->m_key)
            return -1;
        return 0;
    }
    virtual void print()
    {
        printf("CMyNode:%d\n",m_key);
    }

public:
    int m_key;
};

void testCList()
{
    CMyNode* pNode1 = new CMyNode(1);
    CMyNode* pNode2 = new CMyNode(2);
    CMyNode* pNode3 = new CMyNode(3);

    CList list;
    list.clear();
    list.addNode(pNode1);
    list.addNode(pNode2);
    list.addNode(pNode3);

    list.dump();
    list.sortDec();
    list.dump();
    list.sortInc();
    list.dump();

    CMyNode node(3);

    list.dump();
    list.delNode(&node);
    list.dump();
    node.m_key = 2;
    list.delNode(&node);
    list.dump();
    node.m_key = 1;
    list.delNode(&node);
    list.dump();
}

void testCMemHeadList()
{
    TMemBlockHead* pNode1 = new TMemBlockHead;
    TMemBlockHead* pNode2 = new TMemBlockHead;
    TMemBlockHead* pNode3 = new TMemBlockHead;
    pNode1->m_pData = (char*)1;
    pNode1->m_len = 1;
    pNode2->m_pData = (char*)2;
    pNode2->m_len = 2;
    pNode3->m_pData = (char*)3;
    pNode3->m_len = 3;
    

    CMemHeadList list;
    list.clear();
    list.addNode(pNode1);
    list.addNode(pNode2);
    list.addNode(pNode3);

    list.dump();
    list.sortDec();
    list.dump();
    list.sortInc();
    list.dump();

    TMemBlockHead node;
    
    list.dump();
    node.m_pData = (char*)1;
    list.removeNode(&node);
    list.dump();
    node.m_pData = (char*)2;
    list.removeNode(&node);
    list.dump();
    node.m_pData = (char*)3;
    list.removeNode(&node);
    list.dump();

    delete pNode1;
    delete pNode2;
    delete pNode3;
}

void testCBigMemMgr()
{
    char* pBuff = (char*)malloc(1024);
    printf("buff addr = %p,size = %d\n\n",pBuff,1024);
    
    CBigMemMgr memMgr;
    memMgr.init(pBuff,1024);
    memMgr.dump();

    char* p1 = memMgr.malloc(20);
    char* p2 = memMgr.malloc(40);
    char* p3 = memMgr.malloc(60);
    memMgr.dump();
    printf("p1=%p,p2=%p,p3=%p\n",p1,p2,p3);

    memMgr.free(p1);
    memMgr.dump();
    
    memMgr.free(p2);
    memMgr.dump();

    memMgr.free(p3);
    memMgr.dump();

    free(pBuff);
}

void testSimpleQueue()
{
    CSimpleQueue<int> simpleQueue;
    int a = 1;
    simpleQueue.put(a);a++;
    simpleQueue.put(a);a++;
    simpleQueue.put(a);
    printf("%d\n",simpleQueue.get());
    printf("%d\n",simpleQueue.get());
    printf("%d\n",simpleQueue.get());
}

void testSimpleStack()
{
    CSimpleStack<int> simpleStack;
    int a = 1;
    simpleStack.put(a);a++;
    simpleStack.put(a);a++;
    simpleStack.put(a);
    printf("%d\n",simpleStack.get());
    printf("%d\n",simpleStack.get());
    printf("%d\n",simpleStack.get());
}

enum EState
{
    ENormalState = 0,
    EEstablished ,
    EClosed
};

class CNormalState : public CState
{
public:
    CNormalState():CState("NormalState"){}
    ~CNormalState(){}
    int pushState(CPushStateMsg& msg,CStateMachineCtx& ctx)
    {
        printf("in st %s\n",name());
        printf("set content1 to ctx1\n");
        ctx.set(0,"ctx1","content1");
        printf("out st %s\n",name());
        return EEstablished;
    }
};

class CEstablishState : public CState
{
public:
    CEstablishState():CState("EstablishState"){}
    ~CEstablishState(){}
    int pushState(CPushStateMsg& msg,CStateMachineCtx& ctx)
    {
        printf("in st %s\n",name());
        printf("get ctx1:%s\n",ctx.get(0));
        printf("out st %s\n",name());
        return EClosed;
    }
};

class CCloseState : public CState
{
public:
    CCloseState():CState("CloseState"){}
    ~CCloseState(){}
    int pushState(CPushStateMsg& msg,CStateMachineCtx& ctx)
    {
        printf("in st %s\n",name());
        printf("get ctx1:%s\n",ctx.get(0));
        printf("out st %s\n",name());
        return ENormalState;
    }
};

void testStateMachine()
{
    CStateMachine stateMachine("statemachine");
    CNormalState normalState;
    CEstablishState establishState;
    CCloseState closeState;
    stateMachine.registerState(&normalState);
    stateMachine.registerState(&establishState);
    stateMachine.registerState(&closeState);
    CPushStateMsg msg;
    stateMachine.onMessage(msg);
    stateMachine.onMessage(msg);
    stateMachine.onMessage(msg);
}

void testHiredis()
{
    unsigned int j;
    redisContext *c;
    redisReply *reply;

    struct timeval timeout = { 1, 500000 }; // 1.5 seconds
    c = redisConnectWithTimeout("127.0.0.1", 6379, timeout);
    if (c == NULL || c->err) {
        if (c) {
            printf("Connection error: %s\n", c->errstr);
            redisFree(c);
        } else {
            printf("Connection error: can't allocate redis context\n");
        }
        exit(1);
    }

    /* PING server */
    reply = (redisReply *)redisCommand(c,"PING");
    printf("PING: %s\n", reply->str);
    freeReplyObject(reply);

    /* Set a key */
    reply = (redisReply *)redisCommand(c,"SET %s %s", "foo", "hello world");
    printf("SET: %s\n", reply->str);
    freeReplyObject(reply);
}

int main()
{
    testHiredis();
    return 0;
}
